home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Copyright 1993, 1994, 1995, 1996 Silicon Graphics, Inc.
- * ALL RIGHTS RESERVED
- * Permission to use, copy, modify, and distribute this software for
- * any purpose and without fee is hereby granted, provided that the above
- * copyright notice appear in all copies and that both the copyright notice
- * and this permission notice appear in supporting documentation, and that
- * the name of Silicon Graphics, Inc. not be used in advertising
- * or publicity pertaining to distribution of the software without specific,
- * written prior permission.
- *
- * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
- * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
- * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
- * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
- * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
- * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
- * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
- * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
- * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
- * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * US Government Users Restricted Rights
- * Use, duplication, or disclosure by the Government is subject to
- * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
- * (c)(1)(ii) of the Rights in Technical Data and Computer Software
- * clause at DFARS 252.227-7013 and/or in similar or successor
- * clauses in the FAR or the DOD or NASA FAR Supplement.
- * Unpublished-- rights reserved under the copyright laws of the
- * United States. Contractor/manufacturer is Silicon Graphics,
- * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
- *
- * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
- */
- #include "glu.h"
- #include "agl.h"
- #include "tk.h"
-
- #include <math.h>
- #include <stdio.h>
- #include <stdlib.h>
-
- /* XXX */
- #include <string.h>
-
- /*
- extern "C" {
- #include <rgb.h>
- };
- */
-
- #include "Unitdisk.h"
-
- #include "scene.h"
-
- const GLfloat I[16] = {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1
- };
-
- Color white;
- Color black;
-
- #define M_PI 3.14159265359
-
- const double M_2PI = 2.0 * M_PI;
- const float scene_fudge = .000001;
-
- /* Lights are native to the xz plane and are rotated into position -
- * shadows and refraction will not have to be changed if lights are
- * just rotating about the z axis */
- light lights[] = {
- {{1, 0, 0, 1}, {0, 0, 0, 0}, {1, 0, 0, 0},
- {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
- "Red", 1},
- {{0, 1, 0, 1}, {0, 0, 0, 0}, {0, 1, 0, 0},
- {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
- "Green", 1},
- {{0, 0, 1, 1}, {0, 0, 0, 0}, {0, 0, 1, 0},
- {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
- "Blue", 1}
- };
-
- GLfloat light_init_position[nlights][4] =
- {{1.5, 0, 2.5, 1}, {1, 0, 3, 1}, {2, 0, 3, 1}};
- GLfloat light_init_rotation[nlights] = {135, 0, 90};
- GLfloat light_rotation[nlights];
-
- Color world_ambient(.25, .25, .25);
-
- GLfloat index = indices[def_refraction_index].index;
-
- GLfloat square_ambient[4] = {.25, .25, .25, 1};
- GLfloat square_diffuse[4] = {1, 1, 1, 1};
- GLfloat square_specular[4] = {0, 0, 0, 1};
-
- const GLfloat fov = 45.0;
- GLfloat aspect = 1.0;
- GLfloat eyep[3] = {-6, 0, 6};
- GLfloat lookp[3] = {0, 0, 1};
-
-
- /*
- static GLXContext glx_context;
- */
-
- const int max_args = 20;
-
- static int list_square;
- static int lists_shadows;
- static int lists_refraction;
- static int lists_lights = 5;
- static int list_sphere = 4;
- static int list_spheredisk = 9;
- static int list_lights_on = 6;
- static int list_lights_off = 7;
- static int list_light_draw = 8;
-
- int draw_square = 1;
- int draw_shadows = 1;
- int draw_refraction = 1;
- int draw_sphere = 1;
- int draw_lights = 1;
- int draw_texture = 1;
-
- int possible_divisions[] = {10, 20, 30, 40};
-
- // Sphere is stored as floats - more efficient
- GLfloat *spherepts = NULL;
- int nspherepts = 0;
- int spherediv = 0;
- Point_b sphere_position = {0, 0, 1, 1};
- GLfloat sphere_size = .5;
- const GLfloat sphere_ambient[4] = {0, 0, 0, 0};
- const GLfloat sphere_specular[4] = {0, 0, 0, 0};
- Unitdisk sphere_disk;
- static void sphere_build();
- static void sphere_list_init();
- static void sphere_draw();
-
- static void square_list_init();
-
- static void lights_init_onoff();
- static void lights_init_position();
- static void lights_init_position(int i);
- static void lights_list_init2(void);
- static void lights_list_init(int n);
-
- static void light_draw_list_init();
-
- Unitdisk disks[nlights];
- int diskdiv = possible_divisions[def_divisions_index];
- static void disk_build();
- static void disk_build(int disk);
-
-
- Unitdisk shadows[nlights];
- static void shadow_list_init();
- static void shadow_list_init(int n);
- static void shadow_draw(int n);
-
- Unitdisk refraction[nlights];
- static void refraction_list_init();
- static void refraction_list_init(int n);
-
- static void shadow_refraction_full_build();
- static void shadow_refraction_full_build(int n);
-
- void scene_init();
- static void lists_init();
- static void lights_init();
- static int lights_move(int light, float dr, float dphi, float dtheta,
- int update);
- static void lights_move_update(int light, int dr, int dphi, int dtheta);
-
- void scene_draw();
-
- void texture_init();
-
- TK_RGBImageRec *teximage = NULL;
-
- inline float sign(float a)
- {
- // This is badly written so let's not call it too often, ok?
- return (a > 0) ? 1 : (a < 0) ? -1 : 0;
- }
-
- inline double degrees(double a)
- {
- return (a * 180.0 / M_PI);
- }
-
- inline double radians(double a)
- {
- return (a * M_PI / 180.0);
- }
-
- inline double degrees_clamp(double a)
- {
- while (a < 0.0) a += 360.0;
- while (a > 360.0) a -= 360.0;
- return a;
- }
-
- inline double radians_clamp(double a)
- {
- while (a < 0.0) a += M_2PI;
- while (a > M_2PI) a -= M_2PI;
- return a;
- }
-
- void scene_init()
- {
- int i;
-
- white.c[0] = white.c[1] = white.c[2] = white.c[3] = 1;
- black.c[0] = black.c[1] = black.c[2] = 0;
- black.c[3] = 1;
-
- lists_init();
-
-
- for (i = 0; i < nlights; i++)
- {
- lights[i].pos = light_init_position[i];
- light_rotation[i] = light_init_rotation[i];
- lights_init_position(i);
- }
-
- divisions_change(possible_divisions[def_divisions_index]);
-
- lights_init_onoff();
- lights_init();
- lights_init_position();
-
- texture_init();
-
- glClearStencil(0);
-
- // This is for profiling
- // exit(0);
- }
-
- static void scene_project()
- {
- glMatrixMode(GL_PROJECTION);
- //glLoadIdentity();
- gluPerspective(fov, aspect, 0.01, 20.0);
- //glMatrixMode(GL_MODELVIEW);
- //glLoadIdentity();
- gluLookAt(eyep[0], eyep[1], eyep[2], lookp[0], lookp[1], lookp[2], 1, 0, 0);
- }
-
- static void scene_rasterize()
- {
- int i;
-
- glLoadName(name_square);
-
- if (draw_square)
- {
- if (draw_texture) glEnable(GL_TEXTURE_2D);
- //glCallList(list_square);
- square_list_init();
- glDisable(GL_TEXTURE_2D);
- }
-
- if (draw_shadows)
- {
- for (i = 0; i < nlights; i++)
- {
- if (lights[i].on)
- {
- glPushMatrix();
- glRotatef(-light_rotation[i], 0, 0, 1);
- glCallList(lists_shadows + i);
- glPopMatrix();
- }
- }
- }
-
- if (draw_refraction)
- {
- for (i = 0; i < nlights; i++)
- {
- if (lights[i].on)
- {
- glPushMatrix();
- glRotatef(-light_rotation[i], 0, 0, 1);
- glCallList(lists_refraction + i);
- glPopMatrix();
- }
- }
- }
-
- glLoadName(name_sphere);
- /* Drawing the sphere here makes the sphere visible through itself when we
- * do the refraction redraw hack -- for now, just don't draw it */
- // if (draw_sphere) glCallList(list_sphere);
-
- for (i = 0; i < nlights; i++)
- {
- if (draw_lights) glCallList(lists_lights + i);
- }
- }
-
- /* This draws an image of the scene seen through the sphere */
- static void scene_draw_refracted()
- {
- int i;
-
- if (!draw_sphere) return;
-
-
- /* Draw an image of the sphere into the stencil plane -
- * must do this every time in case the lights have moved in front
- * of it */
- glEnable(GL_STENCIL_TEST);
- glClearStencil(0);
- glClear(GL_STENCIL_BUFFER_BIT);
- glStencilFunc(GL_ALWAYS, 0x1, 0x1);
- glStencilOp(GL_REPLACE, GL_KEEP, GL_REPLACE);
-
- glColorMask(0, 0, 0, 0);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- scene_project();
-
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_CULL_FACE);
- glCallList(list_sphere);
- glDisable(GL_CULL_FACE);
- glDisable(GL_DEPTH_TEST);
-
- glColorMask(1, 1, 1, 1);
-
-
- /* Set up a transform with a wider field of view - this is inaccurate
- * but I don't have time to do it right */
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(fov * index, aspect, 0.01, 20.0);
- gluLookAt(eyep[0], eyep[1], eyep[2], lookp[0], lookp[1], lookp[2], 1, 0, 0);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- /* Set up the stencil stuff which will be used to draw the image */
- glStencilFunc(GL_NOTEQUAL, 0x0, 0xffffffff);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
-
- /* Draw the image, gambling that we'll never see anything but the
- * floor through the table */
- glLoadName(name_sphere);
-
- if (draw_texture) glEnable(GL_TEXTURE_2D);
- //if (draw_square) glCallList(list_square);
- square_list_init();
-
- if (draw_shadows)
- {
- for (i = 0; i < nlights; i++)
- {
- if (lights[i].on)
- {
- glPushMatrix();
- glRotatef(-light_rotation[i], 0, 0, 1);
- glCallList(lists_shadows + i);
- glPopMatrix();
- }
- }
- }
-
- if (draw_refraction)
- {
- for (i = 0; i < nlights; i++)
- {
- if (lights[i].on)
- {
- glPushMatrix();
- glRotatef(-light_rotation[i], 0, 0, 1);
- glCallList(lists_refraction + i);
- glPopMatrix();
- }
- }
- }
-
- glDisable(GL_TEXTURE_2D);
-
- /* Draw the sphere to make it look like it
- * has some substance */
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- scene_project();
- glCallList(list_spheredisk);
-
- glDisable(GL_STENCIL_TEST);
- }
-
-
- void scene_draw()
- {
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- scene_project();
-
- /* Should draw an image of the square into the stencil buffer
- * to make sure that refractions which are not on the square do not get
- * drawn, but it can wait. */
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- scene_rasterize();
-
- scene_draw_refracted();
- }
-
- const int pick_maxz = 0xffffffff;
-
- int scene_pick(GLdouble x, GLdouble y)
- {
- GLuint buffer[128];
- GLint vp[4], nhits, nnames;
- GLuint minz, hit = name_background;
- GLint i, j;
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- glGetIntegerv(GL_VIEWPORT, vp);
-
- glSelectBuffer(128, buffer);
- glRenderMode(GL_SELECT);
-
- // Where is this supposed to go, anyway?
- gluPickMatrix(x, vp[3] - y, 1, 1, vp);
-
- scene_project();
-
- glMatrixMode(GL_MODELVIEW);
-
- glInitNames();
- glPushName(name_background);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- scene_rasterize();
- glFlush();
- nhits = glRenderMode(GL_RENDER);
-
- minz = pick_maxz;
- for (i = j = 0; j < nhits; j++)
- {
- nnames = buffer[i];
- i++;
- if (buffer[i] < minz)
- {
- minz = buffer[i];
- hit = buffer[i + 1 + nnames];
- }
-
- i++;
- i += nnames + 1;
- }
-
- if (minz == pick_maxz) return name_background;
- else return hit;
- }
-
- void scene_reset_lights()
- {
- int i;
-
- for (i = 0; i < nlights; i++)
- {
- lights[i].pos = light_init_position[i];
- light_rotation[i] = light_init_rotation[i];
- }
-
- lights_init_position();
- lights_list_init2();
- }
-
- static void square_list_init()
- {
- GLfloat x, y, inc;
- int i, j;
-
- //glNewList(list_square, GL_COMPILE);
- //glLoadName(name_square);
-
- glNormal3f(0, 0, 1);
- glEnable(GL_LIGHTING);
-
- glCallList(list_lights_on);
-
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, square_ambient);
- glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, square_diffuse);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, square_specular);
-
- inc = 10.0 / diskdiv;
- //glEnable(GL_CULL_FACE);
-
- for (i = 0, y = -5.0; i < diskdiv; i++, y += inc)
- {
- glBegin(GL_TRIANGLE_STRIP);
-
- for (j = 0, x = -5.0; j <= diskdiv; j++, x += inc)
- {
- glTexCoord2f(x, y + inc);
- glVertex2f(x, y + inc);
- glTexCoord2f(x, y);
- glVertex2f(x, y);
- }
-
- glEnd();
- }
-
- glDisable(GL_CULL_FACE);
- glCallList(list_lights_off);
- glDisable(GL_LIGHTING);
- //glEndList();
- }
-
- static void spheredisk_list_init()
- {
- glNewList(list_spheredisk, GL_COMPILE);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
- glEnable(GL_LIGHTING);
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
- glEnable(GL_COLOR_MATERIAL);
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, sphere_ambient);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, sphere_specular);
- glCallList(list_lights_on);
- sphere_disk.draw();
- glCallList(list_lights_off);
- glDisable(GL_COLOR_MATERIAL);
- glDisable(GL_LIGHTING);
- glDisable(GL_BLEND);
- glEndList();
- }
-
- void lights_onoff(int light, int val)
- {
- lights[light].on = val;
- lights_init_onoff();
- lights_list_init(light);
- square_list_init();
- }
-
- void refraction_change(GLfloat refraction)
- {
- if (refraction == index) return;
- index = refraction;
- shadow_refraction_full_build();
- refraction_list_init();
- }
-
- void divisions_change(int divisions)
- {
- Point_b eye, look;
-
- if (divisions != spherediv)
- {
- spherediv = divisions;
-
- light_draw_list_init();
- lights_list_init2();
-
- sphere_disk.set_divisions(spherediv, spherediv);
- sphere_disk.fill_points();
- sphere_disk.set_colors(white);
- sphere_disk.scale_alpha_by_z();
- eye = eyep;
- look = lookp;
- sphere_disk.face_direction((eye - look).unit());
- sphere_disk.copy_normals_from_points();
- sphere_disk.scale_translate(sphere_size, sphere_position);
- sphere_build();
- sphere_list_init();
-
- diskdiv = divisions;
- disk_build();
- shadow_refraction_full_build();
- square_list_init();
- spheredisk_list_init();
- shadow_list_init();
- refraction_list_init();
- }
- }
-
- int scene_move(int name, float dr, float dphi, float dtheta, int update)
- {
- switch(name)
- {
- case name_background:
- return 0;
- case name_square:
- return 0;
- case name_sphere:
- return 0;
- default:
- if (name < name_lights || name > name_lights + nlights) return 0;
- return lights_move(name - name_lights, dr, dphi, dtheta, update);
- }
- }
-
- void scene_move_update(int name, int dr, int dphi, int dtheta)
- {
- switch(name)
- {
- case name_background:
- break;
- case name_square:
- break;
- case name_sphere:
- break;
- default:
- if (name < name_lights || name > name_lights + nlights) break;
- lights_move_update(name - name_lights, dr, dphi, dtheta);
- break;
- }
- }
-
-
- static void lights_init_onoff()
- {
- int i;
-
- glNewList(list_lights_on, GL_COMPILE);
-
- for (i = 0; i < nlights; i++)
- {
- if (lights[i].on) glEnable(GL_LIGHT0 + i);
- else glDisable(GL_LIGHT0 + i);
- }
-
- glEndList();
-
- glNewList(list_lights_off, GL_COMPILE);
-
- for (i = 0; i < nlights; i++) glDisable(GL_LIGHT0 + i);
- {
- glEndList();
- }
- }
-
-
-
- static void lights_init_position()
- {
- int i;
-
- for (i = 0; i < nlights; i++) lights_init_position(i);
- }
-
- static void lights_init_position(int i)
- {
- Point_b l, d;
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- l = lights[i].pos;
- l.pt[0] = lights[i].pos.pt[0] * cos(radians(light_rotation[i]));
- l.pt[1] = lights[i].pos.pt[0] * -sin(radians(light_rotation[i]));
-
- d = (sphere_position - l).unit();
- glLightfv(GL_LIGHT0 + i, GL_POSITION, l.pt);
- glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, d.pt);
- }
-
- static void lights_list_init2(void)
- {
- int i;
- for (i = 0; i < nlights; i++) lights_list_init(i);
- }
-
- static void lights_list_init(int n)
- {
- Color c;
-
- glNewList(lists_lights + n, GL_COMPILE);
-
- if (lights[n].on)
- {
- glLoadName(name_lights + n);
-
- glEnable(GL_DEPTH_TEST);
- glEnable(GL_LIGHTING);
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
- glCallList(list_lights_on);
-
- c = lights[n].diffuse;
- glMaterialfv(GL_BACK, GL_AMBIENT, c.c);
- glMaterialfv(GL_BACK, GL_DIFFUSE, black.c);
- glMaterialfv(GL_BACK, GL_SPECULAR, black.c);
-
- glMaterialfv(GL_FRONT, GL_AMBIENT, (c * .75).c);
- glMaterialfv(GL_FRONT, GL_DIFFUSE, white.c);
- glMaterialfv(GL_FRONT, GL_SPECULAR, white.c);
-
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glRotatef(-light_rotation[n], 0, 0, 1);
- glTranslatef(lights[n].pos.pt[0], lights[n].pos.pt[1],
- lights[n].pos.pt[2]);
- glRotatef(-degrees(atan2(lights[n].pos.pt[2] - sphere_position.pt[2],
- lights[n].pos.pt[0])), 0, 1, 0);
- glCallList(list_light_draw);
- glPopMatrix();
-
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
- glDisable(GL_LIGHTING);
- glCallList(list_lights_off);
- glDisable(GL_DEPTH_TEST);
- }
- else
- {
- /* 5.0.1 for Elans seems to object strongly to replacing
- * empty display lists, so will put some stupid command
- * in here */
- glColor3f(0, 0, 0);
- }
-
- glEndList();
- }
-
- static void light_draw_list_init()
- {
- float c, s;
- int t;
-
- glNewList(list_light_draw, GL_COMPILE);
- glEnable(GL_NORMALIZE);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glScalef(.25, .15, .15);
- glBegin(GL_QUAD_STRIP);
-
- for (t = 0; t <= spherediv; t++)
- {
- c = cos(M_2PI * (float)t / (float)spherediv);
- s = sin(M_2PI * (float)t / (float)spherediv);
- glNormal3f(.25, .968*s, .968*c);
- glVertex3f(0, s, c);
- glVertex3f(1, .75*s, .75*c);
- }
-
- glEnd();
- glNormal3f(1, 0, 0);
- glBegin(GL_TRIANGLE_STRIP);
-
- for (t = 0; t <= spherediv; t++)
- {
- c = cos(M_2PI * (float)t / (float)spherediv);
- s = sin(M_2PI * (float)t / (float)spherediv);
- glVertex3f(1, .75*s, .75*c);
- glVertex3f(1, 0, 0);
- }
-
- glEnd();
- glPopMatrix();
- glDisable(GL_NORMALIZE);
- glEndList();
- }
-
- static void lights_init()
- {
- int i;
-
- for (i = 0; i < nlights; i++)
- {
- glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, lights[i].diffuse);
- glLightfv(GL_LIGHT0 + i, GL_SPECULAR, black.c);
- glLightfv(GL_LIGHT0 + i, GL_AMBIENT, black.c);
- glLightf(GL_LIGHT0 + i, GL_SPOT_EXPONENT, 4);
- glLightf(GL_LIGHT0 + i, GL_SPOT_CUTOFF, 90);
- }
-
- glLightfv(GL_LIGHT0 + nlights, GL_DIFFUSE, black.c);
- glLightfv(GL_LIGHT0 + nlights, GL_SPECULAR, black.c);
- glLightfv(GL_LIGHT0 + nlights, GL_AMBIENT, world_ambient.c);
- glEnable(GL_LIGHT0 + nlights);
-
- /* GL_LIGHT0 + nlights + 1 willl eventually be used to draw the
- * refractions - stay tuned. */
- glLightfv(GL_LIGHT0 + nlights + 1, GL_DIFFUSE, black.c);
- glLightfv(GL_LIGHT0 + nlights + 1, GL_SPECULAR, black.c);
- glLightfv(GL_LIGHT0 + nlights + 1, GL_AMBIENT, white.c);
- }
-
- static int lights_move(int light, float dr, float dphi, float dtheta, int update)
- {
- float cphi, sphi, x, y;
- Point_b l, dl;
-
- if (!(dr || dphi || dtheta)) return 0;
-
- l = lights[light].pos - sphere_position;
-
- if (dr)
- {
- dl = l + l*dr;
- if (dl.mag() > sphere_size) l = dl;
- }
-
- if (dphi)
- {
- cphi = cos(dphi);
- sphi = sin(dphi);
- y = -l.pt[0]*sphi + l.pt[2]*cphi;
-
- /* This hack keeps with light from getting below the sphere -
- * the projection sections would completely freak if this ever
- * happened - sphere_size is multiplied by two as a fudge factor*/
- if (y < 2.0*sphere_size)
- {
- dphi = atan2(l.pt[2] - 2.0*sphere_size, l.pt[0]);
- cphi = cos(dphi);
- sphi = sin(dphi);
- }
-
- x = l.pt[0];
- l.pt[0] = x*cphi + l.pt[2]*sphi;
- l.pt[2] = -x*sphi + l.pt[2]*cphi;
- }
-
- if (dtheta)
- {
- light_rotation[light] += degrees(dtheta);
- light_rotation[light] = degrees_clamp(light_rotation[light]);
- }
-
- lights[light].pos = l + sphere_position;
- lights[light].pos.pt[3] = 1;
-
- lights_init_position(light);
- lights_list_init(light);
-
- if (update) lights_move_update(light, dr ? 1 : 0, dphi ? 1 : 0,
- dtheta ? 1 : 0);
- return 1;
- }
-
- static void lights_move_update(int light, int dr, int dphi, int dtheta)
- {
- if (dr)
- {
- disk_build(light);
- shadow_refraction_full_build(light);
- shadow_list_init(light);
- refraction_list_init(light);
- }
- else if (dphi)
- {
- shadow_refraction_full_build(light);
- shadow_list_init(light);
- refraction_list_init(light);
- }
- else if (dtheta)
- {
- }
-
- }
-
-
- static int get_lists(int size)
- {
- int i;
- i = glGenLists(size);
-
- if (size && !i)
- {
- fprintf(stderr, "Unable to allocate %d display lists.\n");
- exit(1);
- }
-
- return i;
- }
-
- static void lists_init()
- {
- //list_square = get_lists(1);
- lists_shadows = get_lists(nlights);
- lists_refraction = get_lists(nlights);
- lists_lights = get_lists(nlights);
- list_sphere = get_lists(1);
- list_spheredisk = get_lists(1);
- list_lights_on = get_lists(1);
- list_lights_off = get_lists(1);
- list_light_draw = get_lists(1);
-
- // sphere_build();
- }
-
- static inline int sphere_npoints()
- {
- return (spherediv+1)*spherediv*3;
- }
-
- void sphere_build()
- {
- int nspherepts;
- int r, t, index;
- float c, s;
-
- delete spherepts;
- nspherepts = sphere_npoints();
- if (nspherepts == 0) return;
- spherepts = new GLfloat[nspherepts];
-
- index = 0;
- for (r = 0; r <= spherediv; r++)
- {
- spherepts[index++] = sin(M_PI * (float)r / (float)spherediv);
- spherepts[index++] = 0;
- spherepts[index++] = -cos(M_PI * (float)r / (float)spherediv);
- }
-
- for (t = 1; t < spherediv; t++)
- {
- c = cos(2.0 * M_PI * (float)t / (float)spherediv);
- s = sin(2.0 * M_PI * (float)t / (float)spherediv);
-
- for (r = 0; r <= spherediv; r++)
- {
- spherepts[index++] = c*spherepts[r*3];
- spherepts[index++] = s*spherepts[r*3];
- spherepts[index++] = spherepts[r*3 + 2];
- }
- }
- }
-
- void sphere_list_init()
- {
- glNewList(list_sphere, GL_COMPILE);
- sphere_disk.draw_by_perimeter();
- glEndList();
- }
-
- void sphere_draw()
- {
- int r, t, p1, p2;
-
- for (t = 1; t < spherediv; t++)
- {
- glBegin(GL_QUAD_STRIP);
- p1 = (t - 1) * (spherediv + 1);
- p2 = t * (spherediv + 1);
-
- for (r = 0; r <= spherediv; r++, p1++, p2++)
- {
- glNormal3fv(&spherepts[p1*3]);
- glVertex3fv(&spherepts[p1*3]);
- glNormal3fv(&spherepts[p2*3]);
- glVertex3fv(&spherepts[p2*3]);
- }
-
- glEnd();
- }
-
- glBegin(GL_QUAD_STRIP);
- p1 = (spherediv + 1) * (spherediv - 1);
- p2 = 0;
-
- for (r = 0; r <= spherediv; r++, p1++, p2++)
- {
- glNormal3fv(&spherepts[p1*3]);
- glVertex3fv(&spherepts[p1*3]);
- glNormal3fv(&spherepts[p2*3]);
- glVertex3fv(&spherepts[p2*3]);
- }
- glEnd();
- }
-
- static void disk_build()
- {
- int i;
- for (i = 0; i < nlights; i++) disk_build(i);
- }
-
- static void disk_build(int disk)
- {
- Point_b light;
- light = lights[disk].pos;
-
- disks[disk].free_points_normals();
- disks[disk].free_colors();
-
- disks[disk].set_divisions(diskdiv, diskdiv);
- disks[disk].set_angle(2.0 *
- acos(sphere_size / light.dist(sphere_position)));
- disks[disk].fill_points();
- }
-
- static void shadow_list_init()
- {
- int i;
- for (i = 0; i < nlights; i++) shadow_list_init(i);
- }
-
- static void shadow_list_init(int n)
- {
- Color c(square_ambient[0], square_ambient[1], square_ambient[2]);
-
- c *= world_ambient;
-
- glNewList(lists_shadows + n, GL_COMPILE);
- glColorMask(lights[n].shadow_mask[0], lights[n].shadow_mask[1],
- lights[n].shadow_mask[2], lights[n].shadow_mask[3]);
- glDisable(GL_DEPTH_TEST);
- glColor3fv(c.c);
- shadows[n].draw_by_perimeter(0, 0, 1);
- glColorMask(1, 1, 1, 1);
- glEndList();
- }
-
- static void refraction_list_init()
- {
- int i;
- for (i = 0; i < nlights; i++) refraction_list_init(i);
- }
-
- static void refraction_list_init(int n)
- {
- /* This could be loads simpler if it weren't for the texture mapping -
- * that's where all this weirdness with GL_LIGHT0 + nlights + 1 comes
- * in */
- glNewList(lists_refraction + n, GL_COMPILE);
-
- glEnable(GL_LIGHTING);
- glCallList(list_lights_off);
- /* This is white ambient light */
- glEnable(GL_LIGHT0 + nlights + 1);
- glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, black.c);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black.c);
- glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
- glEnable(GL_COLOR_MATERIAL);
-
- glBlendFunc(GL_ONE, GL_ONE);
- glEnable(GL_BLEND);
-
- glDisable(GL_DEPTH_TEST);
- refraction[n].draw();
-
- glDisable(GL_BLEND);
-
- glDisable(GL_COLOR_MATERIAL);
- glDisable(GL_LIGHT0 + nlights + 1);
- glDisable(GL_LIGHTING);
-
- glEndList();
- }
-
- static void shadow_refraction_full_build()
- {
- int i;
- for (i = 0; i < nlights; i++) shadow_refraction_full_build(i);
- }
-
- /* This entire function is written a bit oddly... */
- static void shadow_refraction_full_build(int n)
- {
- Color c;
- float dist_light;
- Point_b dlight, zaxis;
-
- /* Make sure that we're starting over from scratch */
- shadows[n].free_points_normals();
- shadows[n].free_colors();
- refraction[n].free_points_normals();
- refraction[n].free_colors();
-
- dlight = lights[n].pos - sphere_position;
- dist_light = dlight.mag();
- dlight.unitize();
- zaxis.pt[0] = 0;
- zaxis.pt[1] = 0;
- zaxis.pt[2] = 1;
-
- shadows[n].set_divisions(disks[n].get_rdivisions(),
- disks[n].get_tdivisions());
- refraction[n].set_divisions(disks[n].get_rdivisions(),
- disks[n].get_tdivisions());
-
- shadows[n].alloc_points();
- shadows[n].face_direction(dlight, disks[n]);
- shadows[n].scale_translate(sphere_size, sphere_position);
-
- c = square_diffuse;
- c *= lights[n].diffuse;
-
- refraction[n].copy_points(disks[n]);
- refraction[n].set_colors(c);
- refraction[n].scale_colors_by_z();
-
- refraction[n].scale(sphere_size);
- refraction[n].refract_normals(zaxis * dist_light, index);
- refraction[n].face_direction(dlight);
-
- refraction[n].project_borrow_points(shadows[n]);
- refraction[n].free_normals();
- shadows[n].project(lights[n].pos);
- if (index != 1.0) refraction[n].scale_colors_by_darea(shadows[n]);
- }
-
- int scene_load_texture(char *texfile)
- {
- teximage = tkRGBImageLoad(texfile);
-
- if (teximage == NULL) return 0;
- else return 1;
-
- return 0;
- }
-
- void texture_init()
- {
- if (teximage == NULL) return;
-
- gluBuild2DMipmaps(GL_TEXTURE_2D, 3, teximage->sizeX, teximage->sizeY,
- GL_RGB, GL_UNSIGNED_BYTE, (const void *) teximage->data);
-
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glRotatef(90, 0, 0, 1);
-
- glTranslatef(.5, .5, 0);
- glScalef(.1, .1, 1);
- glMatrixMode(GL_MODELVIEW);
-
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- //GL_NEAREST_MIPMAP_NEAREST);
- //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
- //GL_LINEAR);
-
- /* New */
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- }
-